#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include "mylist.h"
#include "myqueue.h"
#include "mystack.h"

Queue create_input_queue(int inNumOfElements,int inNumOfZero);
void display_input_queue(Queue inQueue1,Queue inQueue2,int inNumOfElements);
Queue create_result_queue(Queue inQueue1,Queue inQueue2,int inNumOfElements);
void display_queue(Queue inQueue);
Queue return_distinct_queue_values(Queue inQueueSrc);

int main() 
{
	int iChoice=0,iNumElements=0,iNumElements1=0,iNumElements2=0,iNumOfZero=0,i,*pData;
	Queue qQueue1,qQueue2,qResult; 
	Stack sStack;

	printf("****************************************************************\n");
	printf("      Exercise 2			\n");
	printf("							\n");
	printf("      Oren Attia			\n");
	printf("      ID:29074333			\n");
	printf("							\n");
	printf("      Computer Science		\n"); 
	printf("							\n");
	printf("****************************************************************\n");

	while(iChoice!=3)
	{
		printf("1. Exercise 1 \n");
		printf("2. Exercise 2 \n");
		printf("3. EXIT\n");
		printf("Enter your choice : ");
		scanf("%d",&iChoice);
		switch(iChoice)
			{
				case 1 :
					{
						printf("Enter Number of Elements for Queue 1 : ");
						scanf("%d",&iNumElements1);
						printf("\n");
						printf("Enter Number of Elements for Queue 2 : ");
						scanf("%d",&iNumElements2);
						printf("\n\n");

						if(iNumElements1 == iNumElements2)
						{
							printf("Elements for Queue 1 : \n");
							qQueue1=create_input_queue(iNumElements1,0);
							printf("Elements for Queue 2 : \n");
							qQueue2=create_input_queue(iNumElements2,0);
						}
						else
							if(iNumElements1 < iNumElements2)
							{
								iNumOfZero=(iNumElements2-iNumElements1);
								printf("Elements for Queue 1 : \n");
								qQueue1=create_input_queue(iNumElements1,iNumOfZero);
								printf("Elements for Queue 2 : \n");
								qQueue2=create_input_queue(iNumElements2,0);	
							}
							else
							{
								iNumOfZero=(iNumElements1-iNumElements2);
								printf("Elements for Queue 1 : \n");
								qQueue1=create_input_queue(iNumElements1,0);
								printf("Elements for Queue 2 : \n");
								qQueue2=create_input_queue(iNumElements2,iNumOfZero);	
							}

						if(iNumElements1>iNumElements2)
							iNumElements=iNumElements1;
						else
							iNumElements=iNumElements2;
						display_input_queue(qQueue1,qQueue2,iNumElements);

						printf("\n\n");

						qResult=create_result_queue(qQueue1,qQueue2,iNumElements);
						printf("Result Queue\n");
						display_queue(qResult);

						printf("\n\n");
						printf("The Complexity of this <Exercise 1> is: O(n) !");
						printf("\n\n");

					break;
					}			
				case 2 :
					{
						printf("Enter Number of Elements for Given Queue : ");
						scanf("%d",&iNumElements);
						printf("\n");
				
						qQueue1=create_input_queue(iNumElements,0);

						printf("\n\n");

						display_queue(qQueue1,iNumElements);

						printf("\n\n");

						qResult=return_distinct_queue_values(qQueue1);

						printf("\n\n");
						printf("Elements for Source Queue\n");
						display_queue(qQueue1);

						printf("\n\n");
						printf("Elements for Return Queue\n");
						display_queue(qResult);

						printf("\n\n");
						printf("The Complexity of this <Exercise 2> is: O(n) !");
						printf("\n\n");


						deleteQueue(qQueue1);
						deleteQueue(qResult);
					break;
					}
				case 3 :
					exit(0);
				default:
					{
						printf("Invalid choice\n");
						getch();
					break;
					}
			}
		getch();
	}
return 0;
}

Queue create_input_queue(int inNumOfElements,int inNumOfZero)
{
	Queue tmpQ,tmpQReturn;
	int   *tmpData,tmpNum=0,i,tmpDisplayNum=0,tmpCumulator=1 ;

	tmpQ=initQueue();
	tmpQReturn=initQueue();

	for(i=0;i<inNumOfZero;i++) 
	{
		if((tmpData=(int *)malloc(sizeof(int))) == NULL)
			return NULL;

		*tmpData=0;
		enqueue(tmpQ,tmpData);
	}

	for(i=0;i<inNumOfElements;i++)
	{
		if((tmpData=(int *)malloc(sizeof(int))) == NULL)
			return NULL;
	
		printf("Enter Digit {0-9} - No[%2d]",i);
		scanf("%d",&tmpNum);
		printf("\n");

		*tmpData=tmpNum;

		tmpDisplayNum+=(tmpCumulator*tmpNum);
		tmpCumulator=tmpCumulator*10;

		enqueue(tmpQ,tmpData);
	}

return tmpQ;
}

Queue create_result_queue(Queue inQueue1,Queue inQueue2,int inNumOfElements)
{
	Queue tmpQReturn;
	Stack tmpSResult;
	int   *tmpData1,*tmpData2,*tmpReturn,tmpTotal=0,tmpDigit=0,tmpAccumulator=0,i;

	tmpQReturn=initQueue();
	tmpSResult=initStack();

	tmpAccumulator=pow(10,inNumOfElements-1);

	for(i=0;i<inNumOfElements;i++)
	{

		tmpData1=dequeue(inQueue1);
		tmpData2=dequeue(inQueue2);

		tmpTotal+=(*tmpData1 + *tmpData2)*tmpAccumulator;
		tmpAccumulator=tmpAccumulator/10;
	}

	while(tmpTotal!=0)
	{
		tmpDigit=tmpTotal%10;
		tmpTotal=tmpTotal/10;

		if((tmpReturn=(int *)malloc(sizeof(int))) == NULL)
				return NULL;

		*tmpReturn=tmpDigit;
		Push(tmpSResult,tmpReturn);
	}

	while(!stackEmpty(tmpSResult))
	{
		tmpReturn=Pop(tmpSResult);
		enqueue(tmpQReturn,tmpReturn);
	}

return tmpQReturn;
}

void display_input_queue(Queue inQueue1,Queue inQueue2,int inNumOfElements)
{
	int i,*tmpElement1,*tmpElement2;
	Queue tmpQueue1,tmpQueue2;

	tmpQueue1=copyQueue(inQueue1,sizeof(int));
	tmpQueue2=copyQueue(inQueue2,sizeof(int));

	printf("Queue 1 \tQueue 2\n");
	printf("\n");
	printf("First   \tFirst \n");
	printf("------- \t-------\n");
	for(i=0;i<inNumOfElements;i++)
	{
		tmpElement1=dequeue(tmpQueue1);
		tmpElement2=dequeue(tmpQueue2);
		printf("|%3d|\t\t|%3d|\n",*tmpElement1,*tmpElement2);
	}
	printf("------- \t-------\n");
	printf("Last    \tLast \n");
}
void display_queue(Queue inQueue)
{
	int *tmpElement;
	Queue tmpQueue;

	tmpQueue=copyQueue(inQueue,sizeof(int));

	printf("\n");
	printf("First\n");
	printf("-------\n");
	while(!isQueueEmpty(tmpQueue))
	{
		tmpElement=dequeue(tmpQueue);
		printf("|%3d|\n",*tmpElement);
	}
	printf("-------\n");
	printf("Last\n");
}

Queue return_distinct_queue_values(Queue inQueueSrc)
{
	Queue tmpQueueCopy,tmpQueueTrg;
	int   *tmpData1,*tmpData2,tmpDigits[10]={0};

	tmpQueueTrg=initQueue();
	tmpQueueCopy=copyQueue(inQueueSrc,sizeof(int));

	while(!isQueueEmpty(inQueueSrc))
	{
		tmpData1=dequeue(inQueueSrc);
		
		tmpDigits[*tmpData1]=tmpDigits[*tmpData1]++;
	}

	while(!isQueueEmpty(tmpQueueCopy))
	{
		tmpData1=dequeue(tmpQueueCopy);
		enqueue(inQueueSrc,tmpData1);

		if(tmpDigits[*tmpData1]>0)
		{
			tmpDigits[*tmpData1]=(tmpDigits[*tmpData1]) * (*tmpData1);

			if(!tmpDigits[*tmpData1]==0)
			{
				if((tmpData2=(int *)malloc(sizeof(int))) == NULL)
					return NULL;

				*tmpData2=tmpDigits[*tmpData1];
				enqueue(tmpQueueTrg,tmpData2);
			}

			tmpDigits[*tmpData1]=0;
		}
	}

return tmpQueueTrg;
}






